const Config = require('./../config/base_config.js');
const Storage = require('./../utils/storage.js');
const Util = require('./../utils/util.js')

const BASE_URL = Config.API_HOST;

class Request {
  constructor() {
    this.interceptors = {
      request: [],
      response: [],
    };
    this.pendingRequests = new Set();
    this.isRefreshingToken = false;
    this.loadingTimer = null;
    this.tokenRefreshQueue = [];
    this.loadingCount = 0; // 新增加载计数器
  }

  // 添加请求拦截器
  useRequestInterceptor(fulfilled, rejected) {
    this.interceptors.request.push({
      fulfilled,
      rejected
    });
  }

  // 添加响应拦截器
  useResponseInterceptor(fulfilled, rejected) {
    this.interceptors.response.push({
      fulfilled,
      rejected
    });
  }

  // 显示带超时的loading
  showLoadingWithTimeout() {
    // 先清除已有的loading和定时器
    wx.hideLoading();
    if (this.loadingTimer) {
      clearTimeout(this.loadingTimer);
      this.loadingTimer = null;
    }
    wx.showLoading({
      title: '加载中...',
      mask: true
    });

    // 10秒后自动隐藏loading
    this.loadingTimer = setTimeout(() => {
      this.loadingCount++;
      if (this.loadingCount === 1) { // 只有第一个请求显示loading
        wx.showLoading({
          title: '加载中...',
          mask: true
        });
        
        this.loadingTimer = setTimeout(() => {
          this.hideLoading();
        }, 3000);
      }
    }, 3000);
  }
  hideLoading() {
    this.loadingCount--;
    if (this.loadingCount <= 0) {
      wx.hideLoading();
      if (this.loadingTimer) {
        clearTimeout(this.loadingTimer);
        this.loadingTimer = null;
      }
      this.loadingCount = 0; // 重置计数器
    }
  }
  // 清除用户数据
  clearUserData() {
    // --测试先不清除
    Storage.remove('access_token');
    Storage.remove('refresh_token');
    Storage.remove('userInfo');
  }

  // 跳转到登录页
  navigateToLogin() {
    const pages = getCurrentPages();
    const currentRoute = pages[pages.length - 1].route;

    if (!currentRoute.includes('login')) {
      wx.navigateTo({
        url: '/pages/login/index'
      });
    }
  }

  // 处理HTTP错误状态码
  handleHttpError(statusCode) {
    // 先清除loading和定时器
    wx.hideLoading();
    if (this.loadingTimer) {
      clearTimeout(this.loadingTimer);
      this.loadingTimer = null;
    }

    const errorMap = {
      400: '请求参数错误',
      401: '登录已过期，请重新登录',
      403: '拒绝访问',
      404: '请求地址不存在',
      500: '服务器内部错误',
      502: '网关错误',
      503: '服务不可用',
      504: '网关超时'
    };

    wx.showToast({
      title: errorMap[statusCode] || `请求失败，状态码: ${statusCode}`,
      icon: 'none',
      duration: 2000,
      mask: true
    });

    // 401处理 - 延迟跳转
    if (statusCode === 401) {
      setTimeout(() => {
        this.clearUserData();
        this.navigateToLogin();
      }, 2000);
    }
  }

  // 封装wx.request为Promise
  wxRequest(config) {
    return new Promise((resolve, reject) => {
      wx.request({
        ...config,
        success: (res) => {
          resolve(res);
        },
        fail: (err) => {
          reject(err);
        }
      });
    });
  }

  // 处理响应数据
  async processResponse(response) {
    let res = response;

    // 响应拦截器处理
    for (const interceptor of this.interceptors.response) {
      res = await interceptor.fulfilled(res) || res;
    }

    if (res.statusCode === 200) {
      // 增加业务层面的Token过期判断
      if (res.data.code === 401 || res.data.code === 'TOKEN_EXPIRED') {
        throw {
          type: 'token_expired',
          message: res.data.message || 'Token已过期',
          data: res.data
        };
      }

      if (res.data.code === 0 || res.data.success) {
        return res.data;
      } else {
        throw {
          type: 'business',
          message: res.data.message || '请求失败',
          data: res.data
        };
      }
    } else {
      throw {
        type: 'http',
        statusCode: res.statusCode,
        data: res
      };
    }
  }

  // 处理请求错误
  handleRequestError(error) {
    // 确保loading被清除
    wx.hideLoading();
    if (this.loadingTimer) {
      clearTimeout(this.loadingTimer);
      this.loadingTimer = null;
    }

    if (error.type === 'http') {
      this.handleHttpError(error.statusCode);
    } else if (error.type === 'token_expired') {
      wx.showToast({
        title: error.message || '登录已过期',
        icon: 'none',
        duration: 2000
      });
      setTimeout(() => {
        this.clearUserData();
        this.navigateToLogin();
      }, 2000);
    } else {
      wx.showToast({
        title: error.message || '请求失败',
        icon: 'none',
        duration: 2000
      });
    }
  }

  // 检查Token是否即将过期（提前5分钟检查）
  isTokenExpiringSoon() {
    const token = Storage.get('access_token');
    console.log(token)
    if (!token) return true;

    try {
      // 小程序环境可能需要使用wx.base64ToArrayBuffer
      const payloadBase64 = token.split('.')[1];
      const payloadJson = decodeURIComponent(
        atob(payloadBase64)
        .split('')
        .map(c => '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2))
        .join('')
      );
      const payload = JSON.parse(payloadJson);

      if (payload.exp && typeof payload.exp === 'number') {
        // 提前5分钟检查
        return payload.exp * 1000 - Date.now() < 5 * 60 * 1000;
      }
      return true;
    } catch (e) {
      return true;
    }
  }
  async refreshToken() {
    console.log(this.isRefreshingToken)
    if (this.isRefreshingToken) {
      console.log('Token刷新中，加入队列等待');
      return new Promise((resolve, reject) => {
        this.tokenRefreshQueue.push({
          resolve,
          reject
        });
      }).then((result) => {
        // 确保返回的结果包含access_token
        return { 
          access_token: Storage.get('access_token'),
          refresh_token: Storage.get('refresh_token')
        };
      });
    }

    this.isRefreshingToken = true;
    try {
      const refreshToken = Storage.get('refresh_token');
      console.log(refreshToken)
      if (!refreshToken) throw new Error('Missing refresh token');

      const result = await this.post('/auth/refresh', {
        refresh_token: refreshToken
      }, {
        skipAuth: true
      });
      // 确保响应数据结构正确
      const newAccessToken = result.data?.access_token || result.access_token;
      const newRefreshToken = result.data?.refresh_token || result.refresh_token;
      const access_expires_in = Util.timeToSeconds(result.data?.access_expires_in || result.access_expires_in);
      const refresh_expires_in = Util.timeToSeconds(result.data?.refresh_expires_in || result.refresh_expires_in);
      if (!newAccessToken) throw new Error('无效的Token响应');

      // 修正存储逻辑
      Storage.set('access_token', newAccessToken, access_expires_in);
      if (newRefreshToken) {
        Storage.set('refresh_token', newRefreshToken,refresh_expires_in);
      }

      // 关键修复：重新发起队列中的请求
      while (this.tokenRefreshQueue.length) {
        const {
          resolve
        } = this.tokenRefreshQueue.shift();
        resolve({
          access_token: newAccessToken,
          refresh_token: newRefreshToken
        }); // 触发队列中的请求重试
      }

      return {
        access_token: newAccessToken,
        refresh_token: newRefreshToken
      };
    } catch (error) {
      // 处理队列中的错误
      while (this.tokenRefreshQueue.length) {
        const {
          reject
        } = this.tokenRefreshQueue.shift();
        reject(error);
      }

      // 清除无效 Token 并跳转登录
      if (error.response?.status === 401) {
        this.clearUserData();
        this.navigateToLogin();
      }

      throw error;
    } finally {
      this.isRefreshingToken = false;
    }
  }

  // 主动检查并刷新Token
  async checkAndRefreshToken() {
    console.log('检查Token状态...');
    if (this.isTokenExpiringSoon()) {
      console.log('Token即将过期，尝试刷新...');
      try {
        const result = await this.refreshToken();
        console.log('Token刷新结果:', result);
        console.log('新Token:', Storage.get('access_token'));
        return true;
      } catch (error) {
        console.error('刷新Token失败:', error);
        this.clearUserData();
        this.navigateToLogin();
        return false;
      }
    }
    return true;
  }

  // 带重试机制的请求
  async requestWithRetry(url, options = {}, retries = 1) {
    console.log(url)
    console.log(options)
    const requestKey = `${url}_${JSON.stringify(options)}`;
    this.pendingRequests.add(requestKey);

    try {
      // 请求拦截器处理
      let config = {
        url: `${BASE_URL}${url}`,
        method: options.method || 'GET',
        data: options.data || {},
        header: {
          'content-type': 'application/json',
          'Authorization': `Bearer ${Storage.get('access_token') || ''}`,
          ...options.header
        },
        timeout: options.timeout || 60000
      };

      for (const interceptor of this.interceptors.request) {
        config = await interceptor.fulfilled(config) || config;
      }

      // 跳过认证的请求不检查Token
      if (!options.skipAuth) {
        console.log('携带token的请求')
        const tokenValid = await this.checkAndRefreshToken();
        console.log(tokenValid)
        if (!tokenValid) {
          throw new Error('Token无效，请重新登录');
        }
      }

      this.showLoadingWithTimeout();

      try {
        const response = await this.wxRequest(config);
        const processedResponse = await this.processResponse(response);
        return processedResponse;
      } catch (error) {
        // Token过期自动刷新
        if ((error.type === 'token_expired' || error.statusCode === 401) && retries > 0) {
          try {
            await this.refreshToken();
            // 更新请求头中的Token
            config.header.Authorization = `Bearer ${Storage.get('access_token') || ''}`;
            return this.requestWithRetry(url, options, retries - 1);
          } catch (refreshError) {
            // 刷新Token失败，跳转登录
            this.clearUserData();
            this.navigateToLogin();
            throw new Error('登录已过期，请重新登录');
          }
        }
        throw error;
      }
    } catch (error) {
      this.handleRequestError(error);
      throw error;
    } finally {
      this.pendingRequests.delete(requestKey);
      this.hideLoading(); // 使用新的hideLoading方法
    }
  }

  // 主请求方法
  async request(url, options = {}) {
    return this.requestWithRetry(url, options);
  }

  // 快捷方法
  get(url, data, options = {}) {
    return this.request(url, {
      method: 'GET',
      data,
      ...options
    });
  }

  post(url, data, options = {}) {
    return this.request(url, {
      method: 'POST',
      data,
      ...options
    });
  }

  put(url, data, options = {}) {
    return this.request(url, {
      method: 'PUT',
      data,
      ...options
    });
  }

  delete(url, data, options = {}) {
    return this.request(url, {
      method: 'DELETE',
      data,
      ...options
    });
  }

  // 上传文件
  upload(url, filePath, name, formData = {}, options = {}) {
    const requestKey = `upload_${url}_${filePath}`;
    this.pendingRequests.add(requestKey);

    return new Promise((resolve, reject) => {
      this.showLoadingWithTimeout();

      // 检查Token是否有效
      const checkToken = async () => {
        if (this.isTokenExpiringSoon() && !options.skipAuth) {
          try {
            await this.refreshToken();
            return true;
          } catch (error) {
            this.handleRequestError(error);
            reject(error);
            return false;
          }
        }
        return true;
      };

      checkToken().then(valid => {
        if (!valid) return;

        wx.uploadFile({
          url: `${BASE_URL}${url}`,
          filePath,
          name,
          formData,
          header: {
            'Authorization': `Bearer ${Storage.get('access_token') || ''}`,
            ...options.header
          },
          success: (res) => {
            try {
              const data = res.statusCode === 200 ? JSON.parse(res.data) : res.data;
              if (res.statusCode === 200) {
                resolve(data);
              } else {
                this.handleHttpError(res.statusCode);
                reject(data);
              }
            } catch (e) {
              reject(e);
            }
          },
          fail: (err) => {
            this.handleRequestError(err);
            reject(err);
          },
          complete: () => {
            this.pendingRequests.delete(requestKey);
            wx.hideLoading();
            if (this.loadingTimer) {
              clearTimeout(this.loadingTimer);
              this.loadingTimer = null;
            }
          }
        });
      });
    });
  }
}

// 创建实例
const http = new Request();

// 示例拦截器配置
http.useRequestInterceptor(
  (config) => {
    console.log('请求拦截器 - 请求前', config);
    return config;
  },
  (error) => {
    return Promise.reject(error);
  }
);

http.useResponseInterceptor(
  (response) => {
    console.log('响应拦截器 - 响应后', response);
    return response;
  },
  (error) => {
    if (error.statusCode === 403) {
      wx.showModal({
        title: '权限不足',
        content: '当前账号没有权限访问此功能',
        showCancel: false
      });
    }
    return Promise.reject(error);
  }
);

module.exports = http;